{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model I/O - Prompt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## PromptTemplate 字符串提示模版\n",
    "\n",
    "字符串提示模版最终形成的提示是以字符串形式存在的，在字符串模版中可以有多个占位符，每个占位符就是一个变量，后续可以将变量的位置替换成对应的字符串。\n",
    "格式化模版的时候，可以使用 f-strings（默认）或 jinja2 语法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "引入类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import PromptTemplate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1、使用构造函数创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 使用构造函数创建\n",
    "template = \"\"\"\\\n",
    "秋水札记，定位于 {product1} AI 编程推广，分享 {product2} 商业与技术。\n",
    "\"\"\"\n",
    "prompt = PromptTemplate(input_variables=[\"product1\",\"product2\"], template=template)\n",
    "print(prompt.format(product1=\"LangChain\", product2=\"AI\"))\n",
    "print(prompt.format_prompt(product1=\"LangChain\", product2=\"AI\").to_messages())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2、使用from_template方法，模版字符串创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# 使用from_template方法创建\n",
    "template = \"\"\"\\\n",
    "秋水札记，定位于 {product1} AI 编程推广，分享 {product2} 商业与技术。\n",
    "\"\"\"\n",
    "prompt_multiple = PromptTemplate.from_template(template)\n",
    "print(prompt_multiple.format(product1=\"LangChain\", product2=\"AI\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3、使用from_file方法创建，模版文件创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 假设有一个名为\"model_io_prompt.txt\"的文件，其中包含模板字符串\n",
    "# 文件内容: \"秋水札记，定位于 {product1} AI 编程推广，分享 {product2} 商业与技术。\"\n",
    "template_path = \"model_io_prompt.txt\"\n",
    "prompt_from_file = PromptTemplate.from_file(template_path)\n",
    "print(prompt_from_file.format(product1=\"LangChain\", product2=\"AI\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4、partial方法多次对 prompt 提示模版进行赋值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### partial方法字符串赋值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化模板，其中包含了两个变量：product1和product2\n",
    "template_str = \"秋水札记，定位于 {product1} AI 编程推广，分享 {product2} 商业与技术。\"\n",
    "prompt = PromptTemplate.from_template(template_str)\n",
    "\n",
    "# 对模板进行partial处理，先填充product1变量\n",
    "partial_prompt = prompt.partial(product1=\"langchain\")\n",
    "print(partial_prompt)\n",
    "\n",
    "# 使用partial处理后的模板，赋值剩余的product2变量\n",
    "# 最后一步赋值操作需要用format方法\n",
    "final_statement = partial_prompt.format(product2=\"AI\")\n",
    "print(final_statement)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### partial方法函数赋值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "\n",
    "def get_product_name():\n",
    "    # 这里的逻辑可以根据实际情况动态决定product2的值\n",
    "    # 为了示例，我们直接返回\"AI\"\n",
    "    return \"AI\"\n",
    "\n",
    "# 更新模板字符串以包含三个参数，并预先为product3赋值\n",
    "prompt = PromptTemplate(\n",
    "    template=\"{product3}，定位于 {product1} AI 编程推广，分享 {product2} 商业与技术。\",\n",
    "    input_variables=[\"product1\", \"product2\"],\n",
    "    partial_variables={\"product3\": \"秋水札记\"}  # 在构造方法中预先为product3赋值\n",
    ")\n",
    "\n",
    "# 使用函数Partial处理，这里我们假设product1始终为\"LangChain\"\n",
    "partial_prompt = prompt.partial(product1=\"LangChain\", product2=get_product_name)\n",
    "\n",
    "# 格式化时，我们不需要再传递任何变量，因为它们已通过Partial处理被填充\n",
    "final_statement = partial_prompt.format()\n",
    "print(final_statement)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ChatPromptTemplate 聊天提示模版"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "引入类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import ChatPromptTemplate,AIMessagePromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate\n",
    "from langchain.schema import AIMessage, HumanMessage, SystemMessage\n",
    "from langchain import PromptTemplate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1、使用构造方法创建"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用SystemMessage、HumanMessage、AIMessage通过具体提示文本创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# SystemMessage、HumanMessage、AIMessage\n",
    "# 这种类型组成的message，content赋值只能是字符串，不能是模版\n",
    "messages =   [\n",
    "    SystemMessage(content='秋水札记，定位于 LangChain AI 编程推广，分享 LangChain 商业与技术。'),\n",
    "    HumanMessage(content='帮我列出几个AI商业案例？')\n",
    " ]\n",
    "\n",
    "#构造方法创建提示模版\n",
    "prompt = ChatPromptTemplate(messages=messages)\n",
    "\n",
    "# 格式化模板\n",
    "formatted_prompt_message = prompt.format_messages()\n",
    "print(\"format_messages()执行后返回List[BaseMessage] 对象：\")\n",
    "print(formatted_prompt_message)\n",
    "\n",
    "print(\"\\n每一个BaseMessage 对象：\")\n",
    "for msg in formatted_prompt_message:\n",
    "    print(msg.content)\n",
    "\n",
    "formatted_prompt = prompt.format()\n",
    "print(\"\\nformat()执行后返回字符串：\")  \n",
    "print(formatted_prompt)    \n",
    "\n",
    "formatted_format_prompt = prompt.format_prompt()\n",
    "print(\"\\nformat_prompt()执行后返回PromptValue 对象：\")   \n",
    "print(formatted_format_prompt)   \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用SystemMessagePromptTemplate、HumanMessagePromptTemplate、AIMessagePromptTemplate通过提示模版创建"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义变量\n",
    "brand = \"秋水札记\"\n",
    "product_promotion = \"LangChain\"\n",
    "business_case = \"AI商业案例\"\n",
    "\n",
    "# 使用构造函数创建提示模板\n",
    "# 这里的 messages 列表直接使用了字符串格式的消息，\n",
    "# 但同样可以根据需要扩展为更复杂的消息提示模板\n",
    "messages =   [\n",
    "    SystemMessagePromptTemplate(\n",
    "        prompt = PromptTemplate(input_variables=[], \n",
    "                                template='{brand}，定位于 LangChain AI 编程推广，分享 {product_promotion} 商业与技术。')\n",
    "    ),HumanMessagePromptTemplate(\n",
    "        prompt = PromptTemplate(input_variables=[], \n",
    "                                template='帮我列出几个{business_case}')\n",
    "    )\n",
    "]\n",
    "\n",
    "prompt = ChatPromptTemplate(input_variables=[], messages=messages)\n",
    "\n",
    "# 格式化并输出模板\n",
    "formatted_prompt = prompt.format_messages(brand=brand, product_promotion=product_promotion, business_case=business_case)\n",
    "print(\"format_messages()执行后返回List[BaseMessage] 对象：\")\n",
    "print(formatted_prompt)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2、使用from_messages创建，使用包含元组（tuple）的列表（list）结构创建模版"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "template = ChatPromptTemplate.from_messages([\n",
    "    (\"system\", \"{brand}，定位于 LangChain AI 编程推广，分享 {product_promotion} 商业与技术。\"),\n",
    "    HumanMessagePromptTemplate(\n",
    "        prompt = PromptTemplate(input_variables=[], \n",
    "                                template='帮我列出几个{business_case}')\n",
    "    ),\n",
    "    AIMessage(content='语音助手、聊天机器人和对话式AI。')\n",
    "])\n",
    "\n",
    "messages = template.format_messages(\n",
    "    brand=\"秋水札记\",\n",
    "    product_promotion=\"LangChain\",\n",
    "    business_case=\"AI商业案例\"\n",
    ")\n",
    "\n",
    "print(messages)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## FewShotPromptTemplate 少样本提示模版"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "引入类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain import PromptTemplate\n",
    "from langchain.prompts import FewShotPromptTemplate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1、创建一个少样例提示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义示例\n",
    "examples = [\n",
    "    {\"title\": \"今日份的小确幸\", \"content\": \"早上的一杯咖啡，让忙碌的生活暂时按下暂停键。在这个小小的瞬间，找到了自己的小确幸。\"},\n",
    "    {\"title\": \"一个人的西藏\", \"content\": \"独自一人踏上西藏之旅，每一步都是风景，每一刻都是故事。这里的蓝天白云，让我忘记了世界的喧嚣。\"},\n",
    "    {\"title\": \"夏日防晒必备良品\", \"content\": \"分享我这个夏天最爱的防晒霜，轻薄不油腻，让我在炎炎夏日也能享受阳光而不畏惧。\"}\n",
    "]\n",
    "\n",
    "example_prompt = PromptTemplate(\n",
    "    input_variables=[\"title\", \"content\"], template=\"标题: {title}\\n内容：{content}\"\n",
    ")\n",
    "\n",
    "# print(example_prompt.format(**examples[0]))\n",
    "\n",
    "# 创建 FewShotPromptTemplate\n",
    "fewShotprompt = FewShotPromptTemplate(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    example_separator=\"\\n\\n\",\n",
    "    prefix=\"想要创作出具有小红书风格的内容，请参考以下示例：\",\n",
    "    suffix=\"根据上述示例，尝试创作一个{user_input}。\",\n",
    "    input_variables=[\"user_input\"]\n",
    ")\n",
    "\n",
    "# 生成提示\n",
    "print(fewShotprompt.format(user_input=\"新的故事\"))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
